// 预先生成十六进制字符串查找表
const hexStrings = new Array(256);
for (let i = 0; i < 256; i++) {
	let d = '';
	let ch = ((i >> 4) & 0x0F).toString(16);
	d += ch.toUpperCase();
	ch = (i & 0x0F).toString(16);
	d += ch.toUpperCase();
	hexStrings[i] = d;
}

// 字节数组转十六进制字符串
export function hexString(b) {
	let d = '';
	for (const byte of b) {
		d += hexStrings[byte & 0xFF];
	}
	return d;
}

// 字节数组转可打印字符串（控制字符特殊处理）
export function dumpString(b) {
	let d = '';
	for (let i = 0; i < b.length; i++) {
		const c = String.fromCharCode(b[i]);
		if (c.charCodeAt(0) <= 31 || c.charCodeAt(0) === 127) {
			switch (c) {
				case '\r':
					d += "{CR}";
					break;
				case '\n':
					d += "{LF}";
					break;
				case '\0':
					d += "{NULL}";
					break;
				case '\x01':
					d += "{SOH}";
					break;
				case '\x02':
					d += "{STX}";
					break;
				case '\x03':
					d += "{ETX}";
					break;
				case '\x04':
					d += "{EOT}";
					break;
				case '\x05':
					d += "{ENQ}";
					break;
				case '\x06':
					d += "{ACK}";
					break;
				case '\x07':
					d += "{BEL}";
					break;
				case '\x10':
					d += "{DLE}";
					break;
				case '\x15':
					d += "{NAK}";
					break;
				case '\x16':
					d += "{SYN}";
					break;
				case '\x1C':
					d += "{FS}";
					break;
				case '\x1E':
					d += "{RS}";
					break;
				default:
					d += `[${hexStrings[b[i] & 0xFF]}]`;
					break;
			}
		} else {
			d += c;
		}
	}
	return d;
}

// 字节数组指定范围转十六进制字符串
export function hexStringRange(b, offset, len) {
	let d = '';
	const end = offset + len;
	for (let i = offset; i < end; i++) {
		d += hexStrings[b[i] & 0xFF];
	}
	return d;
}

// 十六进制字节数组转普通字节数组
export function hex2byte(b, offset, len) {
	const d = new Uint8Array(len);
	for (let i = 0; i < len * 2; i++) {
		const shift = i % 2 === 1 ? 0 : 4;
		const index = (i >> 1);
		const digit = parseInt(String.fromCharCode(b[offset + i]), 16);
		d[index] |= digit << shift;
	}
	return d;
}


function encodeUtf8(s) {
	const bytes = [];
	for (let i = 0; i < s.length; i++) {
		let code = s.charCodeAt(i);
		if (code <= 0x7F) {
			bytes.push(code);
		} else if (code <= 0x7FF) {
			bytes.push(0xC0 | (code >> 6), 0x80 | (code & 0x3F));
		} else {
			bytes.push(0xE0 | (code >> 12), 0x80 | ((code >> 6) & 0x3F), 0x80 | (code & 0x3F));
		}
	}
	return new Uint8Array(bytes);
}

// 十六进制字符串转字节数组
export function hex2byteFromString(s) {
	if (s.length % 2 === 0) {
		const buf = encodeUtf8(s);
		return hex2byte(buf, 0, s.length >> 1);
	} else {
		return hex2byteFromString("0" + s);
	}
}
export function formatHexString(hexStr) {
	// 移除所有非16进制字符并转为小写
	const cleaned = hexStr.replace(/[^0-9A-Fa-f]/g, '').toLowerCase();

	// 每2个字符插入连字符
	return cleaned.match(/.{1,2}/g)?.join('-') || '';
}